(好的我知道標題沒押韻很虛,我盡力了)
昨天我們終於處理完Database的東東,並且成功用Django加入我們的資料了
今天我們就要改用API來新增資料啦
廢話不多說,咱們累狗
API,應用程式介面
是一種計算介面,它定義多個軟體中介之間的互動
以及可以進行的呼叫(call)或請求(request)的種類
如何進行呼叫或發出請求,應使用的資料格式,應遵循的慣例等 -- from wikipedia
講這麼多,API最簡單的概念就是
你今天對API丟了一個東西進去,然後你希望API給你要的東西出來,有時候也可能希望沒有
簡單來說就是你去扭蛋
你丟了10塊、20塊、50塊或60塊進去,你希望這個看起來完全不堅固的東東能給你一個轉蛋出來
這個扭蛋機就是一個API
API的輸入就是你的蔣公或是你的孫中山
輸出就是一顆扭蛋
有沒有,你平常日常生活處處可見API啊
那為什麼提到API會用林俊傑的殺手歌詞當標題呢
因為這東西,寫不好,你家的程式碼就會變得非常恐怖
前面的設定參數那些東東我們還可以寫的隨興一點
到這裡時我們就要嚴陣以待了
不然你家的code可能就會像本菜雞前人寫的code這樣
@api_view(['POST', 'GET', 'PUT'])
@permission_classes([AllowAny])
def user_function(request):
if request.method == "GET":
email = request.user.email
...
return JsonResponse(data={"data": b_to_json_object(CustomerEmailUserSerializer(c).data), "status": True},
status=status.HTTP_200_OK)
if request.method == "POST":
try:
l.info("method {}, user_function, data: {}".format(request.method, request.data))
data = request.data
except:
return JsonResponse(data={"message": "need json format", "status": False},
status=status.HTTP_406_NOT_ACCEPTABLE)
email = data.get('email', None)
check_account = CustomerEmailUser.objects.filter(email = email)
if len(check_account) >= 1:
print(check_account[0].account_type)
if check_account[0].account_type == 'T':
...
elif check_account[0].account_type == 'F':
...
try:
validate_email(email)
if len(email) > 99:
return JsonResponse(data={"message": "too length", "status": False},
status=status.HTTP_406_NOT_ACCEPTABLE)
except:
return JsonResponse(data={"message": "plz using correct email", "status": False},
status=status.HTTP_406_NOT_ACCEPTABLE)
...
if email and password or account_type:
...
if request.method == 'PUT':
...
而且由於這段是還在實際運行的code,我已經盡量刪減很多冗長的code了
但這架構還是恐怖的跟鬼故事一樣,你就知道在編寫code時保持可讀性的重要性了
而至於如何寫出一個漂亮的code,最近也剛好拜讀了一篇也是本屆鐵人賽的unit test主題文章
https://ithelp.ithome.com.tw/users/20107429/ironman/3897
內容雖然有些多,但每篇都是實打實的知識點
比我這個畫虎爛的菜雞有料多了,也建議大家可以去看一下這篇鐵人主題
真的可以學到平時忽略的東西
好啦回到正題,要想讓你的API保持活性以及可讀性
想當然爾,寫code時的紀律就很重要啦
但畢竟這次主題篇幅有限,我們的aws都還沒開工勒
所以要如何在python做unit test,有機會我們會再開個鐵人賽跟大家講解
現在我們會把重點著重在如何完成你人生第一道法式組合餐
不過寫的過程我也會提醒一下如何避免寫出很醜的code
以免你把其他接手code的人給醜死了
好的剛剛前面提到,我們要寫一個API,必須要戰戰兢兢,小心不要把別人醜死了
那要怎麼避免把別人醜死呢
通常我寫CODE時會有三大要點(當然基本上一定更多啦,這邊就只是講個基礎的方向)
通常這是寫code新手很容易犯的錯誤
因為為了要趕快讓功能上線,看到這個function只有一兩行程式碼
幸尚寬,何為不可
於是就把功能給加到這個function底下了
於是越加越多,越加越多
結果等到BUG發生時,才發現那個出BUG的code早已被埋在function底下的茫茫大海中
那你找BUG自然就找到天荒地老
想當年在大學時期時,本菜雞也很常發生的事情
在某個function寫了個好棒棒的功能
然後發現另一個input也要做差不多相同的事,只是參數有點不一樣
怎麼辦呢
在開一個funciton複製貼上啊,多方便
於是這樣開了又開開了又開
一個小小的class直接塞了1000多行程式碼
現在看當年那個比菜雞還菜的coding style,也是不勝唏噓啊
這個不廢話,上圖比較快
看到這種code,100個人內應該會有101個吐血,啊有一個吐兩次的
講到這邊,你就會發現一件事情
這三個地雷點,咱們上面的CODE全部都犯過一輪了
所以你就知到本菜雞當時看CODE多痛苦了
最痛苦的事情是每次要改規格就是牽一髮動全身
然後菜雞的頭頭每次code reviews又會被挖苦說為什麼CODE這麼蠢
外加多被下一堆規則
真的是有苦難言啊
好啦,不管你多麼的怕雷到你的後人
醜媳婦總是要見公婆的
這種東西就是多練就會了
所以我們就趕快練習吧
首先我們先開啟views.py,我們大部分的API都在這運作
然後這邊就要來介紹Atom的方便功能啦
你可以一邊開啟models.py,另一邊開啟views.py
就像這樣
我們就可以邊寫code邊比對啦
基於我們這支API只是測試而已,因此我們就把function name取做test_api吧
然後由於他是要透過外部連結call過來的,所以參數要加request
接著就是我們要的功能啦
我們剛剛提到這支API就只要做建立objects,然後儲存的簡單功能就好
所以我們就照上一篇的方式建立、設定屬性,儲存
最後再回傳HTTP Status Code 200
這個HTTP Status Code是啥呢,因為今天篇幅夠長了,咱們下篇講解
所以根據上述規則,我們就可以寫出我們第一支API
因為是第一次寫API,所以我會把註解都給標出來,也可以幫助看一下有沒有違反前面的三大原則
def test_api(request):
#建立新的DBTest object
new_obj = DBTest()
#把新建立的object內的test屬性改成"I love Amane Kanata"
new_obj.test = "I love Amane Kanata"
#儲存object
new_obj.save()
#回傳200,這裡使用JsonResponse,data記得回傳格式為dict
return JsonResponse(data={'msg':'add object success.'}, status=200)
然後也別忘了前面要再import相關套件
from django.http import JsonResponse #剛剛的JsonResponse套件
from stonks_index.models import DBTest #從models.py import DBTest 物件
好的,views.py的部分就完成了,接下來就是url的部分啦
首先我們先開stonks_root的urls.py
然後改成下列code
from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
admin.autodiscover()
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^stonks/', include('stonks_index.urls')),
]
這個部分代表著假設我們的url後面開頭是stonks的話就到stonks_index的url做後續動作
接著我們進到stonks_url可以發現
他,沒有urls.py
怎麼辦呢,簡單,建立一個就好了嘛
建立完之後加上這段code
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'test_api/$', views.test_api),
]
這段code代表假設stonks/後面又接著test_api的話就執行views.py內的test_api function
好啦,到此coding部分就完成啦
我們來執行看看,不過執行之前我們先把table內的東西全部砍掉
可是要進去shell也是有點麻煩
那就再加個功能就好啦
我們在views.py再加上下面這段code
def clear_table(request):
#將table所有data撈出來
all_obj = DBTest.objects.all()
#砍掉
all_obj.delete()
#回傳200,這裡使用JsonResponse,data記得回傳格式為dict
return JsonResponse(data={'msg':'clear table success.'}, status=200)
然後我們的stonks_index內的urls.py改成如下
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'test_api/$', views.test_api),
url(r'clear_table/$', views.clear_table),
]
都準備好了我們就可以來執行看看啦
我們執行一次runserver,這裡就不打詳細的指令了
首先先執行http://172.16.15.123:8000/stonks/clear_table/
執行成功,接著執行http://172.16.15.123:8000/stonks/test_api/
執行成功,最後我們再去看一次table資料
執行shell,然後輸入from stonks_index.models import DBTest
接著輸入DBTest.objects.all()
可以看到我們剛剛加入的data,就代表成功啦
以上就是API的介紹,以及寫API時需要注意的事項
下一步我們就會在url request上加點料
以及介紹一個好用的API測試程式
想要知道API還能玩出什麼花樣
且待下回分解~